import time
from typing import Any,Callable

from bases.enum_match_method import MatchMethod
from bases.enum_atest_result import ATestResult
from commons.common import dict_value_2_getkey, get_func_arg_default_type, get_func_kwargs
from commons.public_gobals import PublicGlobals
from windows import testcase_refresh_loop

empty_func = lambda *args,**kwargs:f"这是一个空函数{args, kwargs}"
# 测试用例类
class ATestCase:
    def __init__(self,
                 title='title',   # 测试标题
                 limit_L='',          # 测试下限
                 limit_H='',          # 测试上限
                 match_method:MatchMethod=MatchMethod.no,   # 匹配方式__默认不匹配
                 enable:bool=True,              # 是否启用该用例
                 loop:int=1,                        # 执行次数，与fresh_loop和force_loop一起使用
                 fresh_loop:bool=True,          # 是否开启失败重跑次数___默认开启
                 force_loop:bool=False,         # 是否开启强制跑次数
                 pre_time:int=0,                    # 前置等待时间
                 post_time:int=0,                   # 后置等待时间
                 fail_time:int=0,                   # 失败重跑等待时间
                 case_func:Callable=Callable[...,None],  # 用例调用的函数方法
                 modify_flag:bool = False,
                 modify:int = 0,
                 *args,
                 **kwargs
                 ):
        self.enable:bool = enable
        self.title:str = title
        self.limit_L:Any = limit_L     # 预期结果————低
        self.limit_H:Any = limit_H     # 预期结果————高:等于
        self.match_method:MatchMethod = match_method     # 匹配方式选择

        self.result: Any = None     # 经过用例后看返回值
        # 后置的数据————测试结果
        self.test_result:ATestResult = ATestResult.SKIP

        # 提高通过率用
        self.loop = loop
        self.fresh_loop:bool = fresh_loop        # 失败重跑
        self.force_loop:bool = force_loop        # 不失败也重跑

        # 测试等待————待机
        self.pre_time = pre_time
        self.post_time = post_time
        # 用例跑的函数——————最好用一个列表或者数组进行保存项
        self.case_func = case_func
        # 失败重跑时间
        self.fail_time = fail_time
        # 计时
        self.time:float = 0.0   # 记录时间

        # 添加修正值
        self.modify_flag = modify_flag
        self.modify = modify

        # 函数参数
        self.args = args
        self.kwargs = kwargs
        # 核心
        self.func_args_info = get_func_arg_default_type(self.case_func)
        self.kwargs = get_func_kwargs(self.func_args_info)
        # 进行测试
        # self.testcase()
        # # 匹配结果
        # self.match_result()
        self.limit_args_2_global_value()  # 更新用例中的全局变量

    # 用例执行——————先后期用例返回值，在与预期结果进行对比
    def run(self, command_flag:bool=False):
        self.limit_args_2_global_value()        # 更新用例中的全局变量
        if not self.enable_run:     # 不执行该用例
            self.test_result = ATestResult.SKIP  # 跳过
        elif self.enable_run:
            start = time.time()
            if self.pre_time:
                time.sleep(self.pre_time)
            for i in range(self.loop):
                if command_flag:
                    testcase_refresh_loop.set(i)        # 获取重测次数
                    # print('重测次数：',testcase_refresh_loop.get())

                # self.testcase_func()  # 给出result值
                self.testcase_func_2_result(self.case_func, *self.args, **self.kwargs)
                self.match_result()  # 给出预期值与result的比较
                # return self.test_result
                # 测试结果PASS，且非强制，则结束。
                if self.test_result == ATestResult.PASS and not self.force_loop:
                    break
                if self.test_result == ATestResult.FAIL:    # 如果测试失败，则等待
                    time.sleep(self.fail_time)
            # 后置等待
            if self.post_time:
                time.sleep(self.post_time)
            self.time = round(time.time() - start, 3)
        else:
            self.test_result = ATestResult.SKIP
        return self.test_result

    # # 继承+重写————用这个（暂时废弃）
    # def testcase_func(self):
    #     # self.result == None
    #     pass
    # 建立实例+输入函数得到返回值————用这个
    def testcase_func_2_result(self, func=empty_func, *args, **kwargs):
        print(f'你好你好你好，{args, kwargs}')
        if func:        # 函数存在，才执行
            self.result = func(*args, **kwargs)        # 暂定为 用例的返回值(不做额外处理) 用于 和 limit值进行匹配
            if self.modify_flag:        # 是否启用修正
                self.result += self.modify      # 对结果进行修正

    @property
    def get_test_result(self):
        return self.test_result

    # 获取返回支持使用Global的实例变量
    def get_global_self_value(self)->tuple:
        return self.enable, self.limit_H, self.limit_L  # 目前仅支持enable, limit_H, limit_L

    def limit_args_2_global_value(self):
        for arg in self.get_global_self_value():
            key = dict_value_2_getkey(self.__dict__, arg)
            # print('key::::::::', key)
            if isinstance(arg, str) and arg.startswith('PublicGlobals'):
                # 创建新变量，并等于
                self.__dict__[key+'_run'] = PublicGlobals.__dict__[arg.split('.')[-1]]
            else:
                self.__dict__[key+'_run'] = arg
            print('全局变量转换值:', self.__dict__[key+'_run'])
        # 最后变量被转换成了 原变量+run 的变量。实际判断用带run的。

    def update_func_args_info(self):
        # self.func_args_info = get_func_arg_default_type(self.case_func)
        self.kwargs = get_func_kwargs(self.func_args_info)
        # print('用例info',self.func_args_info)
        # print('用例kwargs',self.kwargs)
        # pass

    def match_result(self):
        try:
            if self.match_method == MatchMethod.no:        # 不匹配
                self.test_result = ATestResult.PASS         # 但是执行
            elif self.match_method == MatchMethod.ne:       # 匹配方式——不等于
                self.test_result = ATestResult.PASS if self.result != self.limit_H_run else ATestResult.FAIL
            elif self.match_method == MatchMethod.eq:      # 匹配方式——等于
                self.test_result = ATestResult.PASS if self.result==self.limit_H_run else ATestResult.FAIL
            elif self.match_method == MatchMethod.gt:      # 匹配方式——大于
                self.test_result = ATestResult.PASS if self.result > self.limit_L_run else ATestResult.FAIL
            elif self.match_method == MatchMethod.ge:      # 匹配方式——大于等于
                self.test_result = ATestResult.PASS if self.result >= self.limit_L_run else ATestResult.FAIL
            elif self.match_method == MatchMethod.lt:      # 匹配方式——小于
                self.test_result = ATestResult.PASS if self.result < self.limit_H_run else ATestResult.FAIL
            elif self.match_method == MatchMethod.le:      # 匹配方式——小于等于
                self.test_result = ATestResult.PASS if self.result <= self.limit_H_run else ATestResult.FAIL
            elif self.match_method == MatchMethod.between:  # 匹配方式——大于某值，小于某值
                self.test_result = ATestResult.PASS if self.limit_L_run <= self.result <= self.limit_H_run else ATestResult.FAIL
        except Exception as e:
            print(e)
            # self.test_result = ATestResult.ERROR
            self.test_result = ATestResult.FAIL


    def __str__(self):
        return '['+self.title+']: '+ self.test_result.value

    def __getitem__(self, item):
        return self[item]

    def __setitem__(self, key, value):
        self[key] = value

    def get_save_args(self):
        # title = 'title', # 测试标题
        # limit_L = None,  # 测试下限
        # limit_H = None,  # 测试上限
        # match_method: MatchMethod = MatchMethod.no,  # 匹配方式__默认不匹配
        # enable: bool = True,  # 是否启用该用例
        # loop = 1,  # 执行次数，与fresh_loop和force_loop一起使用
        # fresh_loop: bool = True,  # 是否开启失败重跑次数___默认开启
        # force_loop: bool = False,  # 是否开启强制跑次数
        # pre_time = 0,  # 前置等待时间
        # post_time = 0,  # 后置等待时间
        # fail_time = 0,  # 失败重跑等待时间
        # modify_flag   # 修正标记
        # modify        # 修正值
        # case_func     # 调用的函数指针
        # func_input_args   # 调用的函数指针指向的函数的参数信息
        return self.title,self.limit_L,self.limit_H,self.match_method.value, self.enable,self.loop,self.fresh_loop,self.force_loop,self.pre_time,self.post_time,self.fail_time, self.modify_flag, self.modify, self.case_func, self.func_args_info
